<template>
  <div style="width: 100%">
    <!-- 回显输入框和激活弹窗的按钮 -->
    <div>
      <el-input v-model="selectedLabel" clearable @blur="handleBlur">
        <template #append>
          <el-button @click="showTables">
            {{ $t('common.action.select', '选择') }}
          </el-button>
        </template>
      </el-input>
    </div>
    <!-- 弹窗 -->
    <vxe-modal
      :title="title ? title : $t('common.title.select', '选择')"
      v-model="show"
      :loading="loading"
      :mask="true"
      :lock-view="true"
      width="70vw"
      height="80vh"
      destroy-on-close
      remember
      lock-scroll
      show-footer
      show-confirm-button
      show-cancel-button
      @confirm="confirmSelection"
      @cancel="show = false"
    >
      <iframe
        ref="iframeRef"
        frameborder="0"
        style="
          display: block;
          width: 100%;
          height: 100%;
          border: 0;
          overflow: hidden;
        "
        :src="target"
      ></iframe>
    </vxe-modal>
  </div>
</template>
<script setup>
/**
 * 这是一个引用某菜单就可以当作单选框或者复选框使用的组件
 * 1.默认所有菜单都可以被引用（具体可以参考“字典数据”菜单和“角色管理”菜单）
 * 1.1 toolbarConfig 需要采用computed根据route.query.selection控制显示或者不显示
 * 1.2 columns 需要采用computed根据route.query.selection控制操作列是否显示（参考 useColumn.js 配置）
 * 1.3 分别针对 radio/checkbox 定义选择事件 checkBoxChangeHandler和 radioChangeHandler
 *
 */
import { smartTranslate as $t, transPlaceholder as $p } from '@/lang';
import request from '@/utils/request';
// 定义 props
const props = defineProps({
  modelValue: {
    type: [Number, Array],
    default: null,
  },
  url: {
    type: String,
    default: '/admin/role',
    required: true,
  },
  api: {
    type: String,
    default: 'admin.role/index',
    required: true,
  },
  type: {
    type: String,
    default: 'checkbox',
  },
  valueField: {
    type: String,
    default: 'id',
  },
  labelField: {
    type: String,
    default: 'name',
  },
  placeholder: {
    type: String,
    default: '请点击选择',
  },
  title: {
    type: String,
    default: '请选择',
  },
});
const emit = defineEmits(['update:modelValue']);
// iframe
const iframeRef = ref();
// 是否显示载入效果
const loading = ref(false);
// 是否显示 el-drawer
const show = ref(false);
// 完整的URL
const target = ref('');
// 显示到输入框中的给用户看的值
const selectedLabel = ref();
// 存储选中的数据
const selectedData = ref([]);
// 最后更新的值
const lastValue = ref([]);

// 显示选择表格
function showTables() {
  if (target.value) {
    show.value = true;
  } else {
    console.error('URL not set correctly');
  }
}

function handleBlur() {
  // 如果最后一次的值不等于当前的值，并且当前的值为空，则认为是清除了
  if (lastValue.value !== '' && selectedLabel.value === '') {
    emit('update:modelValue', null);
  }
  lastValue.value = selectedLabel.value;
}

// 选中后的操作
/**
 * window.parent.postMessage
 * 接收来自 iframe 的消息
 * 并根据 action 进行处理
 * @param event
 */
function handleMessage(event) {
  const { action, safeCheckedRows } = event.data;
  if (action === 'selectRow') {
    selectedData.value = safeCheckedRows;
  }
}

// 选中后的操作
/**
 * 选中后的操作，分别将label和value分别存储到 selectedLabel 和 selectedData 中
 */
function confirmSelection() {
  if (selectedData.value.length > 0) {
    // 更新 modelValue
    if (props.type === 'radio') {
      selectedLabel.value = selectedData.value[0].label;
      emit('update:modelValue', selectedData.value[0].value);
    } else {
      selectedLabel.value = selectedData.value
        .map((item) => item.label)
        .join(',');
      emit(
        'update:modelValue',
        selectedData.value.map((item) => item.value),
      );
    }
    // 关闭弹窗
    show.value = false;
  } else {
    ElMessageBox.alert('请选择数据', '提示', { type: 'error' });
  }
}

// 监听 modelValue 的变化 显示值到 selectedLabel
watch(
  () => props.modelValue,
  (newVal) => {
    // 绑定变量值发生变化，选择的数据行却是0，则查询绑定变量的标签
    if (selectedData.value.length == 0 && newVal) {
      let data = {};
      if (props.type === 'radio') {
        data = { id: [newVal] };
      } else {
        data = { id: newVal };
      }
      request({
        url: props.api,
        method: 'post',
        data,
      }).then(({ data }) => {
        selectedLabel.value = data.data
          .map((item) => item[props.labelField])
          .join(',');
      });
    }
  },
  { immediate: true },
);

// 监听 type 属性的变化，自动更新 target
watch(
  () => props.type,
  (newType) => {
    updateTargetUrl();
  },
  // 立即执行一次
  { immediate: true },
);

// 监听 url 属性的变化，自动为其拼凑 URL
watch(
  () => props.url,
  (newUrl) => {
    if (newUrl) {
      updateTargetUrl();
    } else {
      console.error('URL is empty or undefined');
    }
  },
  // 立即执行一次
  { immediate: true },
);

// 更新 target URL
function updateTargetUrl() {
  const host = window.location.origin;
  const newUrl = props.url;
  const queryStringIndex = newUrl.indexOf('?');
  // 如果是多选 1; 如果是单选 2;
  const nolayoutValue = props.type === 'checkbox' ? '1' : '2';
  // 构造查询字符串
  const params = new URLSearchParams({
    value: props.valueField,
    label: props.labelField,
    nolayout: '1',
    selection: nolayoutValue,
  });
  // 根据newUrl是否存储查询参数，进行拼接
  if (queryStringIndex === -1) {
    target.value = host + '/#' + newUrl + '?' + params.toString();
  } else {
    target.value = host + '/#' + newUrl + '&' + params.toString();
  }
}

onMounted(() => {
  // 监听来自 iframe 的消息
  window.addEventListener('message', handleMessage);
});

onUnmounted(() => {
  // 移除消息监听器
  window.removeEventListener('message', handleMessage);
});

// 暴露方法
defineExpose({
  show() {
    // 展示表单
    showTables();
  },
});
</script>
